#include <iostream>
#include <vector>
#include <unordered_map>
#include <functional>
#include <memory>
#include <unistd.h>


using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask
{
private:
    uint64_t _id;       // 定时器任务对象Id
    uint32_t _timeout;  // 定时任务的超时时间
    bool _canceled;     // false-表示没有被取消，true-表示被取消
    TaskFunc _task_cb;  // 定时器对象要执行的定时任务 
    ReleaseFunc _release;// 用于删除TimerWheel中保存的定时器对象信息
public:
    TimerTask(uint64_t id, uint32_t delay, const TaskFunc& cb)
    :_id(id), _timeout(delay), _task_cb(cb), _canceled(false) {}
    ~TimerTask() 
    {
        if(_canceled == false) _task_cb();
        _release(); 

    }
    void Cancel() { _canceled = true; }
    void SetRelease(const ReleaseFunc& cb) { _release = cb; }
    uint32_t DelayTime() { return _timeout; }
};

//时间轮
using WeakTask = std::weak_ptr<TimerTask>;
using PtrTask = std::shared_ptr<TimerTask>;
class TimeWheel
{
private:
    int _tick;      // 当前的秒针，走到哪释放哪里，相当于执行哪里的任务
    int _capacity;  // 表盘的最大数量，也就是最大延迟时间
    std::vector<std::vector<PtrTask>> _wheel;
    std::unordered_map<uint64_t, WeakTask> _timers;
private:
    void RemoveTimer(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
        {
            _timers.erase(id);
        }
    }
public:
    TimeWheel():_capacity(60), _tick(0), _wheel(_capacity) {}
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc& cb) // 添加定时任务
    {
        PtrTask pt(new TimerTask(id, delay, cb));
        pt->SetRelease(std::bind(&TimeWheel::RemoveTimer, this, id));
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
        _timers[id] = WeakTask(pt);
    }
    void TimerRefresh(uint64_t id)  // 刷新/延迟定时任务
    {
        // 通过保存的定时器对象的weak_ptr构造一个share_ptr出来，添加到轮子中
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return; // 没找到，没法刷新，没法延迟
        }
        PtrTask pt = it->second.lock(); // lock获取weak_ptr管理的对象的share_ptr
        int delay = pt->DelayTime();
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
    }
    void TimerCancel(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return; // 没找到，没法刷新，没法延迟
        }
        PtrTask pt = it->second.lock();
        if(pt) pt->Cancel();
    }
    void RunTimerTask() // 每秒被执行一次
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear();  // 清空指定位置上的数组，就会把数组里的所有管理定时器的对象的share_ptr释放掉 
    }
};

class Test
{
public:
    Test()
    {
        std::cout << "构造" << std::endl;
    }
    ~Test()
    {
        std::cout << "析造" << std::endl;
    }
};
void DelTest(Test* t)
{
    delete t;
}

int main()
{
    TimeWheel tw;
    Test* ts = new Test();
    tw.TimerAdd(888, 5, std::bind(DelTest, ts));

    for(int i = 0; i < 5; i++)
    {
        sleep(1);
        tw.TimerRefresh(888);
        tw.RunTimerTask();
        std::cout << "刷新一下定时任务, 需要5秒后才会销毁" << std::endl;
    }
    tw.TimerCancel(888);
    while(1)
    {
        std::cout << "---------------" << std::endl;
        tw.RunTimerTask();
        sleep(1);
    }
    return 0;
}